# -*- coding: utf-8 -*-
from urllib.parse import quote
from django.http import HttpResponse
from openpyxl.utils import get_column_letter
from openpyxl.workbook import Workbook
from openpyxl.worksheet.table import Table, TableStyleInfo
from openpyxl.styles import Font, PatternFill
from rest_framework.permissions import IsAuthenticated
from rest_framework.decorators import action
from rest_framework.validators import UniqueTogetherValidator

from dvadmin.design.models import Decision, NodeTypes, NodesHierarchy
from dvadmin.design.views.hierarchy import NodesHierarchySerializer
from dvadmin.utils.json_response import DetailResponse, ErrorResponse, SuccessResponse
from dvadmin.utils.serializers import CustomModelSerializer
from dvadmin.utils.viewset import CustomModelViewSet


def combi(seq):
    """
    判定表
    """
    if not seq:
        yield []
    else:
        for element in seq[0]:
            for rest in combi(seq[1:]):
                yield [element] + rest


class DecisionSerializer(CustomModelSerializer):
    """
    判定表法-序列化器
    """

    class Meta:
        model = Decision
        fields = "__all__"
        validators = [
            UniqueTogetherValidator(
                queryset=Decision.objects.all(),
                fields=['name', 'stub', 'factor', 'level'],
                message="名字、桩、项必须唯一"
            )
        ]


class DecisionViewSet(CustomModelViewSet):
    """
    判定表法 接口
    list:查询
    save:新增
    update:修改
    retrieve:单例
    destroy:删除
    """

    queryset = Decision.objects.all()
    serializer_class = DecisionSerializer

    def create(self, request, *args, **kwargs):
        """
        判定表法 新增 eg.
        --------------------
        {
            "name": "项目授信申请31",
            "node_type": "decision",
            "data": [
                {
                    "stub": "condition",
                    "factor": "业务类型",
                    "level": "50万直租标准产品"
                },
                {
                    "stub": "action",
                    "factor": "是否新增合同",
                    "level": "是"
                },
                {
                    "stub": "action",
                    "factor": "是否新增合同",
                    "level": "否"
                }
            ]
        }

        """
        name = request.data.get('name')
        node_type = request.data.get('node_type')
        data = request.data.get('data')

        instance = NodeTypes.objects.filter(description='testmodel').first()
        if instance is None:
            return ErrorResponse(msg="查询出错")

        parent = NodesHierarchy.objects.filter(name=name, node_order=0, node_type=instance, parent=None).first()
        if parent is not None:
            return ErrorResponse(msg="名称已存在")

        # Hierarchy新增1条testmodel，作为根节点
        data_hier = {"name": name, "node_order": 0, "node_type": instance.id, "parent": None}
        serializer = NodesHierarchySerializer(data=data_hier, request=request)
        serializer.is_valid(raise_exception=True)
        parent = serializer.save()

        instance = NodeTypes.objects.filter(description=node_type).first()
        if instance is None:
            return ErrorResponse(msg="查询出错")

        for i, item in enumerate(data):
            # Hierarchy新增1条allpairs，作为叶节点
            data_hier = {"name": name, "node_order": i, "node_type": instance.id, "parent": parent.id}
            serializer = NodesHierarchySerializer(data=data_hier, request=request)
            serializer.is_valid(raise_exception=True)
            hierarchy = serializer.save()

            # AllPairs新增1条，作为详情
            data_pairs = {"name": name, "stub": item['stub'], "factor": item['factor'], "level": item['level'], "hierarchy": hierarchy.id}
            serializer = DecisionSerializer(data=data_pairs, request=request)
            serializer.is_valid(raise_exception=True)
            serializer.save()

        return DetailResponse(msg="成功")

    def list(self, request, *args, **kwargs):
        """判定表法 获取所有测试模型 """

        is_superuser = request.user.is_superuser
        if is_superuser:
            queryset = Decision.objects.all().values_list("hierarchy")
        else:
            dept_list = request.user.role.values_list('dept', flat=True)
            queryset = Decision.objects.filter(dept_belong_id__in=dept_list).values_list("hierarchy")

        queryset = NodesHierarchy.objects.filter(id__in=queryset).values_list("parent")
        queryset = NodesHierarchy.objects.filter(id__in=queryset)
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = NodesHierarchySerializer(page, many=True, request=request)
            return self.get_paginated_response(serializer.data)
        serializer = NodesHierarchySerializer(queryset, many=True, request=request)
        return SuccessResponse(data=serializer.data, msg="成功")

    def retrieve(self, request, *args, **kwargs):
        """判定表法 生成测试模型 """
        pid = kwargs.get('pk')
        is_superuser = request.user.is_superuser
        if is_superuser:
            instance = NodesHierarchy.objects.filter(id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(parent_id=pid)
        else:
            dept_list = request.user.role.values_list('dept', flat=True)
            instance = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, parent_id=pid)
        factors, parameters = self.filter_by('condition', hierarchy)
        conditions = {}
        for index, factor in enumerate(factors):
            conditions[factor] = parameters[index]

        factors, parameters = self.filter_by('action', hierarchy)
        actions = {}
        for index, factor in enumerate(factors):
            actions[factor] = parameters[index]

        data = {"id": instance.id, "name": instance.name, "conditions": conditions, "actions": actions}
        return DetailResponse(data=data, msg="成功")

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def gen(self, request, *args, **kwargs):
        """判定表法 根据测试模型生成测试场景  """

        pid = request.query_params.get('id')
        is_superuser = request.user.is_superuser
        if is_superuser:
            instance = NodesHierarchy.objects.filter(id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(parent_id=pid)
        else:
            dept_list = request.user.role.values_list('dept', flat=True)
            instance = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, parent_id=pid)
        factors, parameters = self.filter_by('condition', hierarchy)
        res = list(combi(parameters))

        data = {"id": instance.id, "name": instance.name, "title": factors}
        page = self.paginate_queryset(res)
        if page is not None:
            data["body"] = page
            return self.get_paginated_response(data)
        data = {"id": instance.id, "name": instance.name, "title": factors, "body": res}
        return DetailResponse(data=data, msg="成功")

    @action(methods=['GET'], detail=False, permission_classes=[IsAuthenticated])
    def export(self, request, *args, **kwargs):
        """判定表法 导出模型和场景 """
        pid = request.query_params.get('id')
        is_superuser = request.user.is_superuser
        if is_superuser:
            instance = NodesHierarchy.objects.filter(id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(parent_id=pid)
        else:
            dept_list = request.user.role.values_list('dept', flat=True)
            instance = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, id=pid).first()
            hierarchy = NodesHierarchy.objects.filter(dept_belong_id__in=dept_list, parent_id=pid)
        response = HttpResponse(content_type="application/msexcel")
        response["Access-Control-Expose-Headers"] = f"Content-Disposition"
        response["content-disposition"] = f'attachment;filename={quote(str(f"导出{instance.name}.xlsx"))}'
        wb = Workbook()
        ws1 = wb.create_sheet(index=0, title='测试建模')
        ws2 = wb.create_sheet(index=1, title='测试场景')

        factors, parameters = self.filter_by('condition', hierarchy)
        data = list(combi(parameters))
        title1 = ['序号', '类型', '名称', '选项']
        ws1, count1, column1 = self.set_table_data(ws1, '条件桩', title1, factors, parameters)
        factors_a, parameters_a = self.filter_by('action', hierarchy)
        ws1, count2, column2 = self.set_table_data(ws1, '动作桩', title1, factors_a, parameters_a)
        row1 = get_column_letter(max(count1, count2))
        column = column1 + column2
        tab1 = Table(displayName="Table1", ref=f"A1:{row1}{column}")

        title2 = ['序号', '测试目的'] + factors + factors_a
        row2 = get_column_letter(len(title2))
        start = get_column_letter(len(title2)-len(factors_a)+1)
        column = 1
        ws2.append(title2)
        for index, results in enumerate(data):
            results_list = []
            for h_index, val in enumerate(results):
                if val is None or val=="":
                    results_list.append("")
                else:
                    results_list.append(val)
            ws2.append([index + 1, instance.name, *results_list])
            column += 1
        # 　更新列宽
        for index in range(len(title2)):
            ws2.column_dimensions[get_column_letter(index + 2)].width = 30
        tab2 = Table(displayName="Table2", ref=f"A1:{row2}{column}")
        style = TableStyleInfo(
            name="TableStyleLight11",
            showFirstColumn=True,
            showLastColumn=False,
            showRowStripes=True,
            showColumnStripes=True,
        )
        tab1.tableStyleInfo = style
        tab2.tableStyleInfo = style
        ws1.add_table(tab1)
        ws2.add_table(tab2)
        font = Font(bold=True, color='FFFFFF')
        fill = PatternFill(start_color='FF6495ED', end_color='FF6495ED', fill_type='solid')
        cells_range1 = ws1[f"A{column1+1}:{row1}{column1+1}"]
        cells_range2 = ws2[f"{start}1:{row2}1"]
        for row in cells_range1:
            for cell in row:
                cell.fill = fill
                cell.font = font
        for row in cells_range2:
            for cell in row:
                cell.fill = fill
        wb.save(response)
        return response

    def filter_by(self, stub, hierarchy):
        """查找 """
        results = Decision.objects.filter(stub=stub, hierarchy__in=hierarchy)
        factors = []
        for result in results:
            factors.append(result.factor)
        factors = list(set(factors))

        parameters = []
        for factor in factors:
            row = []
            parirs = results.filter(factor=factor)
            for pair in parirs:
                row.append(pair.level)
            parameters.append(row)
        return factors, parameters

    def set_table_data(self, ws, stub, title, factors, parameters):
        count = 2  # 列数
        column = 1
        width = 30  # 默认列宽

        ws.append(title)
        for index, results in enumerate(parameters):
            results_list = []
            for h_index, val in enumerate(results):
                if val is None or val == "":
                    results_list.append("")
                else:
                    results_list.append(val)
                count = max(count, 3 + len(results_list))

            ws.append([index + 1, stub, factors[index], *results_list])
            column += 1

        for index in range(count + 1):
            ws.column_dimensions[get_column_letter(index + 2)].width = width
            if index > 3:
                ws.cell(row=1, column=index).value = f"选项{index - 3}"
        return ws, count, column
